package utils

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
	"time"

	"golang.org/x/net/http2"
)

// HttpHead 发送一个Head请求。
// 返回状态码和错误信息
func HttpHead(apiUrl string, params map[string]string, timeout time.Duration) (int, error) {
	// 构建完整URL
	fullUrl := buildFullURL(apiUrl, params)

	// 创建http请求
	req, err := http.NewRequest("HEAD", fullUrl, nil) // 修改为HEAD请求
	if err != nil {
		return 0, fmt.Errorf("创建http请求出错: %w", err)
	}

	// 添加请求头信息
	req.Header.Set("Content-Type", "application/json")

	// 初始化客户端并忽略证书验证
	client := createClient(timeout)

	_ = http2.ConfigureTransport(client.Transport.(*http.Transport))

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		return 0, fmt.Errorf("发送http请求出错: %w", err)
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body) // 直接关闭响应体

	// 返回状态码
	return resp.StatusCode, nil
}

// HttpGet 发送一个GET请求。
// 返回响应体、状态码和错误信息
func HttpGet(apiUrl string, params map[string]string, timeout time.Duration) ([]byte, int, error) {
	// 构建完整URL
	fullUrl := buildFullURL(apiUrl, params)

	// 创建http请求
	req, err := http.NewRequest("GET", fullUrl, nil) // GET请求不应携带body
	if err != nil {
		return nil, 0, fmt.Errorf("创建http请求出错: %w", err)
	}

	// 添加请求头信息
	req.Header.Set("Content-Type", "application/json")

	// 初始化客户端并忽略证书验证
	client := createClient(timeout)
	_ = http2.ConfigureTransport(client.Transport.(*http.Transport))
	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		return nil, 0, fmt.Errorf("发送http请求出错: %w", err)
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body) // 直接关闭响应体

	return readResponseBody(resp)
}

// HttpPost 发送一个带有JSON格式body的POST请求。
// 返回响应体、状态码和错误信息
func HttpPost(apiUrl string, params map[string]string, body any, timeout time.Duration) ([]byte, int, error) {
	var bodyIOReader io.Reader = nil
	if body != nil {
		// 将body参数序列化为JSON
		jsonData, err := json.Marshal(body)
		if err != nil {
			return nil, 0, fmt.Errorf("body参数解析失败: %w", err)
		}
		bodyIOReader = bytes.NewBuffer(jsonData)
	}

	// 构建完整URL
	fullUrl := buildFullURL(apiUrl, params)

	// 创建http请求
	req, err := http.NewRequest("POST", fullUrl, bodyIOReader)
	if err != nil {
		return nil, 0, fmt.Errorf("创建http请求出错: %w", err)
	}

	// 添加请求头信息
	req.Header.Set("Content-Type", "application/json")

	// 初始化客户端并忽略证书验证
	client := createClient(timeout)
	_ = http2.ConfigureTransport(client.Transport.(*http.Transport))
	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		return nil, 0, fmt.Errorf("发送http请求出错: %w", err)
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body) // 直接关闭响应体

	return readResponseBody(resp)
}

// HttpPut 发送一个带有JSON格式body的PUT请求。
// 返回响应体、状态码和错误信息
func HttpPut(apiUrl string, params map[string]string, body any, timeout time.Duration) ([]byte, int, error) {
	var bodyIOReader io.Reader = nil
	if body != nil {
		// 将body参数序列化为JSON
		jsonData, err := json.Marshal(body)
		if err != nil {
			return nil, 0, fmt.Errorf("body参数解析失败: %w", err)
		}
		bodyIOReader = bytes.NewBuffer(jsonData)
	}

	// 构建完整URL
	fullUrl := buildFullURL(apiUrl, params)

	// 创建PUT请求
	req, err := http.NewRequest("PUT", fullUrl, bodyIOReader)
	if err != nil {
		return nil, 0, fmt.Errorf("创建PUT请求失败: %w", err)
	}

	// 设置请求头
	req.Header.Set("Content-Type", "application/json")

	// 初始化客户端并忽略证书验证
	client := createClient(timeout)
	_ = http2.ConfigureTransport(client.Transport.(*http.Transport))
	// 执行请求
	resp, err := client.Do(req)
	if err != nil {
		return nil, 0, fmt.Errorf("发送PUT请求失败: %w", err)
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)

	// 读取响应
	return readResponseBody(resp)
}

// HttpDelete 发送一个DELETE请求。
// 返回状态码和错误信息
func HttpDelete(apiUrl string, params map[string]string, timeout time.Duration) (int, error) {
	// 构建完整URL
	fullUrl := buildFullURL(apiUrl, params)

	// 创建DELETE请求
	req, err := http.NewRequest("DELETE", fullUrl, nil)
	if err != nil {
		return 0, fmt.Errorf("创建DELETE请求失败: %w", err)
	}

	// 初始化客户端并忽略证书验证
	client := createClient(timeout)
	_ = http2.ConfigureTransport(client.Transport.(*http.Transport))
	// 执行请求
	resp, err := client.Do(req)
	if err != nil {
		return 0, fmt.Errorf("发送DELETE请求失败: %w", err)
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)

	// 返回HTTP状态码
	return resp.StatusCode, nil
}

// HttpOptions 发送一个OPTIONS请求。
// 返回响应头、状态码和错误信息
func HttpOptions(apiUrl string, timeout time.Duration) (http.Header, int, error) {
	// 创建OPTIONS请求
	req, err := http.NewRequest("OPTIONS", apiUrl, nil)
	if err != nil {
		return nil, 0, fmt.Errorf("创建OPTIONS请求失败: %w", err)
	}

	// 初始化客户端
	client := createClient(timeout)
	_ = http2.ConfigureTransport(client.Transport.(*http.Transport))
	// 执行请求
	resp, err := client.Do(req)
	if err != nil {
		return nil, 0, fmt.Errorf("发送OPTIONS请求失败: %w", err)
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)

	// 返回响应头
	return resp.Header, resp.StatusCode, nil
}

// HttpTrace 发送一个TRACE请求。
// 返回响应体、状态码和错误信息
func HttpTrace(apiUrl string, timeout time.Duration) ([]byte, int, error) {
	// 创建TRACE请求
	req, err := http.NewRequest("TRACE", apiUrl, nil)
	if err != nil {
		return nil, 0, fmt.Errorf("创建TRACE请求失败: %w", err)
	}

	// 初始化客户端并忽略证书验证
	client := createClient(timeout)
	_ = http2.ConfigureTransport(client.Transport.(*http.Transport))
	// 执行请求
	resp, err := client.Do(req)
	if err != nil {
		return nil, 0, fmt.Errorf("发送TRACE请求失败: %w", err)
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)

	// 读取响应体
	return readResponseBody(resp)
}

// HttpPatch 发送一个带有JSON格式body的PATCH请求。
// 返回响应体、状态码和错误信息
func HttpPatch(apiUrl string, params map[string]string, body any, timeout time.Duration) ([]byte, int, error) {
	var bodyIOReader io.Reader = nil
	if body != nil {
		// 将body参数序列化为JSON
		jsonData, err := json.Marshal(body)
		if err != nil {
			return nil, 0, fmt.Errorf("body参数解析失败: %w", err)
		}
		bodyIOReader = bytes.NewBuffer(jsonData)
	}

	// 构建完整URL
	fullUrl := buildFullURL(apiUrl, params)

	// 创建PATCH请求
	req, err := http.NewRequest("PATCH", fullUrl, bodyIOReader)
	if err != nil {
		return nil, 0, fmt.Errorf("创建PATCH请求失败: %w", err)
	}

	// 设置请求头
	req.Header.Set("Content-Type", "application/json")

	// 初始化客户端并忽略证书验证
	client := createClient(timeout)
	_ = http2.ConfigureTransport(client.Transport.(*http.Transport))
	// 执行请求
	resp, err := client.Do(req)
	if err != nil {
		return nil, 0, fmt.Errorf("发送PATCH请求失败: %w", err)
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)

	// 读取响应体
	return readResponseBody(resp)
}

// 辅助函数，构建完整的请求URL。
func buildFullURL(apiUrl string, params map[string]string) string {
	if len(params) > 0 {
		values := url.Values{}
		for key, value := range params {
			// 清理键和值的产后空格
			values.Set(strings.TrimSpace(key), strings.TrimSpace(value))
		}
		return apiUrl + "?" + values.Encode()
	}
	return apiUrl
}

// 辅助函数，创建一个忽略证书验证的HTTP客户端。
func createClient(timeout time.Duration) *http.Client {
	return &http.Client{
		Timeout: timeout,
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		},
	}
}

// 辅助函数，读取并返回响应体的内容。
func readResponseBody(resp *http.Response) ([]byte, int, error) {
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, 0, fmt.Errorf("读取响应体失败: %w", err)
	}
	return body, resp.StatusCode, nil
}
